package com.nowcoder.community.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.nowcoder.community.annotation.LoginRequired;
import com.nowcoder.community.entity.Comment;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Page;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.event.EventProducer;
import com.nowcoder.community.service.*;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import com.nowcoder.community.util.RedisKeyUtil;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class UserController implements CommunityConstant {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
//导入相关路径
    @Value("${community.path.upload}")
    private String uploadPath;
    @Value("${community.path.domain}")
    private String domain;
    @Value("${server.servlet.context-path}")
    private String contextPath;
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    @Value("${aliyun.oss.url}")
    private String url;
    //文件存储目录
    private String filedir = "header/";

    @Autowired
    private UserService userService;
    @Autowired
    private HostHolder hostHolder;
    @Autowired
    private LikeService likeService;
    @Autowired
    private FollowService followService;
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired
    private CommentService commentService;
    @Autowired
    private EventProducer eventProducer;

    @LoginRequired
    @RequestMapping(path = "/user/setting",method = RequestMethod.GET)
    public String getSetting(){

        return "/site/setting";
    }
    //更改密码
    @LoginRequired
    @RequestMapping(path = "/user/password",method = RequestMethod.POST)
    public String updatePassword(@RequestParam("oldpwd") String oldpwd, @RequestParam("newpwd") String newpwd,@RequestParam("confirmpwd") String confirmpwd,Model model){
        //传入参数为前端页面填入表单数据
        //获取user对象
        User user = hostHolder.getUser();
       //原密码是否正确
        if (!CommunityUtil.md5(oldpwd+user.getSalt()).equals(user.getPassword())){
            model.addAttribute("oldpwdMsg","原始密码错误！");
            return "/site/setting";
        }
        //新密码格式是否正确
        if (newpwd == null || newpwd.isEmpty() || newpwd.trim().isEmpty()){
            model.addAttribute("newpwdMsg","新密码错误！");
            return "/site/setting";
        }
        //新旧密码是否一致
        if (!newpwd.equals(confirmpwd)){
            model.addAttribute("confirmpwdMsg","两次密码不一致！");
            return "/site/setting";
        } else{
            //更改密码写入数据库
            String password = CommunityUtil.md5(newpwd+user.getSalt());
            userService.updatePassword(user.getId(),password);
            return "redirect:/index";
        }
    }
//上传头像 废弃采用aliyun云存储
    @LoginRequired
    @RequestMapping(path = "/user/upload",method = RequestMethod.POST)
    public String uploadHeader(MultipartFile headerImage, Model model){
        if (headerImage.isEmpty()){
            model.addAttribute("error","您还没有选择图片！");
            return "/site/setting";
        } //如果图片为空返回error
        String fileName = headerImage.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1 );
        //只允许上传.jpg和.png文件
        if (StringUtils.isBlank(suffix)||!("jpg".equals(suffix)||"png".equals(suffix)||"jpeg".equalsIgnoreCase(suffix))){
            model.addAttribute("error","文件格式不正确");
            return "/site/setting";
        }

        try {
            //生成随机文件名
            fileName = CommunityUtil.generateUUID() + "." + suffix;
            //Thumbnails处理图片
            BufferedImage bi = Thumbnails.of(headerImage.getInputStream())
                    .scale(0.25f)
                    .asBufferedImage();
            //图片处理为正方形
            int init_width = bi.getWidth();
            int init_height = bi.getHeight();
            if (init_width != init_height){
                int width_height = 0;
                int x = 0;
                int y = 0;
                if (init_width > init_height) {
                    width_height = init_height;//原图是宽大于高的长方形
                    x = (init_width-init_height)/2;
                    y = 0;
                } else if (init_width < init_height) {
                    width_height = init_width;//原图是高大于宽的长方形
                    y = (init_height-init_width)/2;
                    x = 0;
                }
                bi = bi.getSubimage(x, y, width_height, width_height);
            }
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //ImageIO.write(image, "JPEG", out);
            ImageIO.write(bi, suffix, os); //图片写入到 ImageOutputStream 和之前格式一致
           InputStream inputStream = new ByteArrayInputStream(os.toByteArray());

            //文件上传
            //设置文件路径和名称
            String fileUrl = filedir + fileName;
            //上传文件
            //阿里云文件上传客户端  创建OSSClient实例。
            OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            //调用oss方法实现上传
            //参数1：Bucket名称
            //参数2：上传到oss的文件路径和文件名
            //参数3：上传文件输入流
            client.putObject(bucketName, fileUrl, inputStream);
            //删除旧头像
            User user = hostHolder.getUser();

            if ( user.getHeaderUrl() != null){
                String[] objectNames = user.getHeaderUrl().split("/");
                String objectName = filedir + objectNames[4];
                if (objectName != null) {
                    client.deleteObject(bucketName, objectName);
                    logger.info("删除旧头像成功"+objectName);
                    String headerUrl = url + "/" + fileUrl;
                    userService.updateHeader(user.getId(),headerUrl);
                    logger.info("成功更新头像"+headerUrl);
                }
            }

            // 关闭OSSClient
            client.shutdown();
            //更新当前用户头像的路径（web访问 Http://loacalhost:8080/community/user/header/xxx.png）

            //String headerUrl = domain + contextPath +"/user/header/" +fileName;

//确定文件存放的路径
        /*File dest = new File(uploadPath + "/" + fileName);
        try {
            headerImage.transferTo(dest);
            //按指定大小把图片进行缩和放（会遵循原图高宽比例）
            //此处把图片压成400×500的缩略图
            Thumbnails.of(dest).size(400,500).toFile(dest);
            //变为400*300,遵循原图比例缩或放到400*某个高度
        } catch (IOException e) {
            logger.error("上传文件失败"+e.getMessage());
            throw new RuntimeException("上传文件失败，服务器发生异常" + e);
        }*/
            return "redirect:/index";


        } catch (IOException e) {
            model.addAttribute("error",e.getMessage());
            return "/site/setting";
        }



    }

   /* @RequestMapping(path = "/header/{fileName}",method = RequestMethod.GET)
    public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response){
        //服务器存放路径
       fileName = uploadPath + "/" + fileName;
       //文件后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        //相应图片
        response.setContentType("image/"+suffix);
        try(
                FileInputStream fis = new FileInputStream(fileName);
                OutputStream os = response.getOutputStream();
                ) {
            byte[] buffer = new byte[1024];
            int b = 0;
            while ((b = fis.read(buffer)) != -1){
                os.write(buffer,0,b);
            }
        } catch (IOException e) {
            logger.error("读取头像失败！" + e.getMessage());
        }
    }*/

    /**
     *   个人主页
     * @param userId
     * @param model
     * @return
     */
    @RequestMapping(path = "/user/profile/{userId}",method = RequestMethod.GET)
    public String getProfilePage(@PathVariable("userId") int userId,Model model){
        User user = userService.findUserById(userId);
        if (user == null){
            throw new IllegalArgumentException("该用户不存在！");
        }
        //用户
        model.addAttribute("user",user);
        //点赞数量
        int userLikeCount = likeService.findUserLikeCount(userId);
        model.addAttribute("userLikeCount",userLikeCount);
        //关注数量
        long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER);
        model.addAttribute("followeeCount",followeeCount);
        //关注者 粉丝数量
        long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER,userId);
        model.addAttribute("followerCount",followerCount);
        //是否已关注
        boolean hasFollowed = false;
        if (hostHolder.getUser()!=null) {
            hasFollowed = followService.findFolloweeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId);
        }
        model.addAttribute("hasFollowed",hasFollowed);
        return "/site/profile";
    }

    @RequestMapping(path = "/user/my-post/{userId}",method = RequestMethod.GET)
    public String getMyPost(@PathVariable("userId") int userId,Model model, Page page){
        User user = userService.findUserById(userId);
        if (user == null){
            throw new IllegalArgumentException("该用户不存在");
        }
        model.addAttribute("user",user);
//用户发帖总数
        int postsCount = discussPostService.findDiscussPostRows(userId);
        model.addAttribute("postsCount",postsCount);

        page.setRows(postsCount);
        page.setPath("/user/my-post/" + userId);
        //访问帖子列表
        List<DiscussPost> mypostList = discussPostService.findDiscussPosts(userId,page.getOffset(),page.getLimit(),3);
        List<Map<String, Object>> myPosts = new ArrayList<>();
        if(mypostList != null){
            for (DiscussPost post: mypostList) {
                Map<String,Object> map = new HashMap<>();
                map.put("post",post);
                map.put("user",user);
                long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId());
                map.put("likesCount",likeCount);
                myPosts.add(map);
            }
        }
        model.addAttribute("myPosts",myPosts);
        return "/site/my-post";
    }

    @RequestMapping(path = "/user/my-reply/{userId}",method = RequestMethod.GET)
    public String getMyReply(@PathVariable("userId") int userId,Model model, Page page) {
        User user = userService.findUserById(userId);
        if (user == null){
            throw new IllegalArgumentException("该用户不存在");
        }

        model.addAttribute("user",user);

        int commentCount = commentService.findCountByUserId(userId,ENTITY_TYPE_POST);
        model.addAttribute("commentCount",commentCount);

        page.setPath("/user/my-reply/" + userId);
        page.setRows(commentCount);
        //访问帖子列表
        List<Comment> list = commentService.findCommentsByUserId(userId,ENTITY_TYPE_POST, page.getOffset(), page.getLimit());
        List<Map<String, Object>> myComments = new ArrayList<>();
        if(list != null){
            for (Comment comment: list) {
                Map<String,Object> map = new HashMap<>();
                map.put("comment",comment);
                map.put("user",user);
                DiscussPost post = discussPostService.findDiscussPostById(comment.getEntityId());
                map.put("post",post);
                myComments.add(map);
            }
        }
        model.addAttribute("myComments",myComments);
        return "/site/my-reply";
    }

    @RequestMapping(path = "/user/changePasswordByCode", method = {RequestMethod.GET,RequestMethod.POST})
    //修改密码，model变量用来向页面返回数据
    public String changePasswordByCode(String email,String code,String password, Model model,
                                       @CookieValue("codeOwner") String codeOwner) {
        String kaptcha = null;
        try {
            if (StringUtils.isNotBlank(codeOwner)) {
                String redisKey = RedisKeyUtil.getCodeKey(codeOwner);
                kaptcha = (String) redisTemplate.opsForValue().get(redisKey);
            }
        }catch (Exception e) {
            model.addAttribute("codeMsg", "验证码失效!");
            return "/site/forget";
        }


        if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equals(code)) {
            model.addAttribute("codeMsg", "验证码不正确!");
            return "/site/forget";
        }
        Map<String, Object> map = userService.changePasswordByCode(email, password);
        if (map.containsKey("success")) {
            return "redirect:/login";
        } else {
            model.addAttribute("passwordMsg", map.get("passwordMsg"));
            return "/site/forget";
        }
    }

    @RequestMapping(path = "/forget", method = RequestMethod.GET)
    //忘记密码
    public String forgetPassword() {
        return "/site/forget";
    }

    @RequestMapping(path = "/user/sendCode", method = RequestMethod.POST)
    //向邮箱发送验证码
    @ResponseBody
    public String sendCode(String email,HttpServletResponse response){
        User user=userService.findUserByEmail(email);
        if(user==null){
            return CommunityUtil.getJSONString(1,"您输入的邮箱格式有误或未注册");
        }
        userService.sendCode(email,response);
        return CommunityUtil.getJSONString(0);
    }





}
